package ncme.auto.framework.core.dynamicDatasource.utils;

import com.mysql.cj.jdbc.StatementImpl;
import com.mysql.cj.jdbc.result.ResultSetImpl;
import ncme.auto.framework.core.dynamicDatasource.entity.SqlConnectInfo;
import ncme.auto.framework.core.exceptions.AutoException;
import ncme.auto.framework.core.exceptions.ExceptionEnum;
import ncme.auto.framework.core.utils.StringUtil;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author sjh
 */
public class SQLExecutor {

    public Object executeSql(SqlConnectInfo sqlConnectInfo, String sql) {
        try {
            // 加载驱动
            Class.forName(sqlConnectInfo.getDriver());
            try (
                    // 获取数据库连接
                    Connection conn = DriverManager.getConnection(sqlConnectInfo.getUrl(), sqlConnectInfo.getUser(), sqlConnectInfo.getPassword());
                    // 使用Connection来创建一个Statement对象
                    Statement stmt = conn.createStatement();
            ) {
                // 执行DML
                ResultSet resultSet;
                if (sql.contains("INSERT")) {
                    stmt.executeUpdate(sql);
                    long lastInsertID = ((StatementImpl) stmt).getLastInsertID();
                    return Integer.parseInt(String.valueOf(lastInsertID));  //返回生成的主键id
                } else if (sql.contains("UPDATE")) {
                    return stmt.executeUpdate(sql);  //返回影响行数，1为正常更新一行
                } else if (sql.contains("SELECT")) {
                    resultSet = stmt.executeQuery(sql);
                    List<Object> resultList = new ArrayList<>();
                    while (resultSet.next()) resultList.add(setResult(sql, resultSet));
                    return resultList;  //返回查询结果的List<Map>，还需进行类型转换
                } else {
                    throw new AutoException(ExceptionEnum.PLUGIN, "该方法只支持INSERT、UPDATE、SELECT操作");
                }
            }
        } catch (Exception e) {
            throw new AutoException(ExceptionEnum.PLUGIN, "sql执行失败", e);
        }
    }

    public Object setResult(String sql, ResultSet resultSet) {
        try {
            ResultSetImpl resultSet1 = (ResultSetImpl) resultSet;
            if (sql.contains("COUNT( * )")) {
                return Integer.parseInt(resultSet1.getObject(1).toString());
            } else {
                Map<String, Object> rowMap = new HashMap<>();
                List<String> sqlColumnNames = getSqlColumnNames(sql);
                for (String columnName : sqlColumnNames) {
                    Object object = resultSet1.getObject(columnName);
                    rowMap.put(StringUtil.upperCase_(columnName, false), object);
                }
                return rowMap;
            }
        } catch (Exception e) {
            throw new AutoException(ExceptionEnum.JDBC, "结果集处理失败", e);
        }
    }

    private List<String> getSqlColumnNames(String sql) {
        sql = sql.split("SELECT")[1].split("FROM")[0].trim();
        String[] splits = sql.split(",");
        return new ArrayList<>(Arrays.asList(splits));
    }

}
